package cc.linker.steplink.crm.task;

import cc.linker.steplink.crm.commons.MongoDBConstants;
import cc.linker.steplink.crm.commons.RedisConstants;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.lock.RedisLock;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.commons.utils.NumberUtils;
import cc.linker.steplink.crm.domain.PropagationNode;
import cc.linker.steplink.crm.support.oauth.GetOrRefreshToken;
import com.alibaba.fastjson.JSON;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 传播链路同步
 */
@Slf4j
@Component
public class SyncPropagationLinkTask {
    
    @Autowired
    private HttpService httpService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private GetOrRefreshToken getOrRefreshToken;
    
    @Autowired
    private SystemProperties systemProperties;
    
    private final static String PROPAGATION_LINK_URL = "article/share";
    
//    @Async
//    @RedisLock("SyncPropagationLinkTask")
//    @Scheduled(cron = "0 30 1 * * *")
//    @Scheduled(initialDelay = 1000, fixedDelay = 5000)
    public void execute(){// 每次请求5小时数据
        long millsToday = Calendar.getInstance().getTimeInMillis();
        Long start = null;
        Long startMills = 0L;
        long interval = 3600*5L;
        while (startMills < millsToday) {
            start = invoke(start, interval);
            startMills = (start*1000L);
        }
    }

    /**
     * 同步
     * @param start 起始时间
     * @param interval 时间间隔 秒
     */
    public long invoke(Long start, long interval){
        //传播链路数据
        Long time = null;
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.group("_class").max("readTime").as("readTime"));
        AggregationResults<BasicDBObject> latestPropagationNode =
                mongoTemplate.aggregate(aggregation, MongoDBConstants.PROPAGATION_LINK_COLLECTION, BasicDBObject.class);
        for (Iterator iterator = latestPropagationNode.iterator(); iterator.hasNext(); ) {
            Document obj = (Document)iterator.next();
            time = NumberUtils.getLong(obj.get("readTime"));
            //System.out.println(JSON.toJSONString(obj));
        }
        
        String contentUrl = systemProperties.getSync().getTrace();
        if (!contentUrl.endsWith("/")) {
            contentUrl = contentUrl + "/";
        }
        contentUrl = contentUrl + PROPAGATION_LINK_URL;
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        
        // 鉴权
        String accessToken = redisTemplate.opsForValue().get(RedisConstants.CRM_OAUTH_ACCESS_TOKEN);
        if (StringUtils.isEmpty(accessToken)) {
            getOrRefreshToken.refresh();
            accessToken = redisTemplate.opsForValue().get(RedisConstants.CRM_OAUTH_ACCESS_TOKEN);
        }
        headers.put("Authorization", "bearer " + accessToken);

        Map<String, Object> params = new HashMap<>();
        if (time == null) {// 初始无数据设定时间同步
            Calendar startDay= Calendar.getInstance();
            startDay.set(Calendar.YEAR, 2019);
            startDay.set(Calendar.MONTH, 6);
            startDay.set(Calendar.DAY_OF_MONTH, 1);
            startDay.set(Calendar.HOUR_OF_DAY, 0);
            time = startDay.getTimeInMillis()/1000L;
        }
        if (start == null || start <= time) {// 以最新时间为起点
            start = time;
        }
        // 请求5小时数据
        params.put("startTime", start);
        params.put("endTime", start += interval);
        
        String resultJson = "";
        try {
            resultJson = httpService.doGet(contentUrl, params, headers);
        } catch (Exception e) {
            LOGGER.error("传播溯源请求异常：",e);
        }
        
        if (StringUtils.isEmpty(resultJson)) {
            return start;
        }
        
        List<PropagationNode> propagationNodeList = JSON.parseArray(resultJson, PropagationNode.class);
        if (propagationNodeList == null || propagationNodeList.isEmpty()) {
            return start;
        }
        final Long pastTime = time;
        if (pastTime != null) {// 去重
            propagationNodeList =propagationNodeList.stream()
                    .filter(x -> !x.getReadTime().equals(pastTime)).collect(Collectors.toList());
        }
        // 保存本地mongoDB
        if (propagationNodeList.size() > 0) {
            mongoTemplate.insert(propagationNodeList, MongoDBConstants.PROPAGATION_LINK_COLLECTION);
        }
        return start;
    }
}

